#include <iostream>
#include <cmath>
using namespace std;

struct datos{
				double d1;
				double d2;
				double v1;
				double v2;
				double dtot;
				double es;
				double t1;
				double t2;
				double xr;
			};

void ing_datos(datos&);

void obtener_minimo(datos&);

void obtener_tiempo(datos&);

void mostrar_datos(datos);


//Este main tiene poderes de supervaca y llama funciones
int main () {
	        datos d;
	        
			ing_datos(d);
			
			obtener_minimo(d);
			
			obtener_tiempo(d);
			
			mostrar_datos(d);
			
             }

//Esta funcion se utiliza para ingresar los datos conocidos
void ing_datos(datos& d){
						cout << "ingrese la ditancia d1 en metros \n";
						cin >> d.d1;
						cout << "ingrese la distancia d2 en metros\n";
						cin >> d.d2;
						cout << "ingrese velocidad por tierra en metros por segundo \n";
						cin >> d.v1;
						cout << "ingrese la velocidad de nado del baniero, en metros por segundo \n";
						cin >> d.v2;
						cout << "ingrese la distancia total \n";
						cin >> d.dtot;
						cout << "ingrese el error porcentual deseado \n";
						cin >> d.es;
						//convierte el error dado como porcentaje en un numero decimal
						d.es = d.es/100;
					
						}

//Esta funcion implementa el metodo y encuentra el minimo con la funcion derivada
void obtener_minimo(datos& d){

	double f_d,f_d2,xold,ea;
	int contador;
	contador = 0;
	ea=1;
    d.xr=0;
		
		while (ea > d.es) //while error de la iteracion mayor que error aceptado.
			
		{			
			f_d=(d.xr/(d.v1*(sqrt(((pow(d.d1,2.))+(pow(d.xr,2.)))))))+((d.xr-d.dtot)/(d.v2*((sqrt((pow((d.xr-d.dtot),2.))+(pow(d.d2,2.)))))));
			
			f_d2= (((pow(d.d2,2.))/((pow(((pow(d.d2,2.))+(pow((d.dtot-d.xr),2.))),1.5))*d.v2))+((pow(d.d1,2.))/((pow((pow(d.d1,2.))+(pow(d.xr,2.)),1.5))*d.v1)));
			
			xold=d.xr;
			
			d.xr=d.xr-(f_d/f_d2); //aplicacion de newton raphson para optimizacion  donde f_d = derivada primera, f_d2 = derivada segunda y xr valor aproximado del minimo.
			    
            ea = abs((d.xr-xold)/d.xr);
            
            contador++;
			
			}
																		
			cout << "se alcanzo la raiz en " << contador << " iteraciones\n";
																						
							}

//Esta funcion obtiene los tiempos en base a la funcion original usando el valor minimo encontrado
void obtener_tiempo(datos& d){
	
								double x2;

								x2 = d.dtot-d.xr;
     
								d.t1 = (sqrt(((pow(d.d1,2))+(pow(d.xr,2)))))/d.v1;
     
								d.t2 = (sqrt(((pow(d.d2,2))+(pow(x2,2)))))/d.v2;
     
	
							}

//Muestra en pantalla los datos obtenidos con las funciones
void mostrar_datos(datos d){
							cout << "La distancia recorrida por la playa sera: " << d.xr << "metros" << "\n";
							
							cout << "La distancia por mar sera: " << d.dtot-d.xr << "metros"<< "\n";
							
							cout << "El tiempo total hasta banista sera : " ;
							
							cout << d.t1+d.t2 << "s" <<  "\n" << "tiempo por la playa " ;
							
							cout<< d.t1 << "s" << "\ntiempo por mar " << d.t2 << "s" <<"\n";
	
															}
